﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once
#include "GcmpModelInterface.h"
#include <unordered_map>

namespace gcmp
{
    class IElement;
    class IDocument;

    /// \brief 拷贝操作器
    class GCMP_MODEL_INTERFACE_EXPORT ICopyOperator
    {
    public:
        /// \brief 获取内建拷贝操作器
        ///
        /// \return const ICopyOperator * 获取拷贝操作器指针
        static const ICopyOperator * Get(void);

    public:
        /// \brief 拷贝Element对象
        ///
        /// \param pSourceElement 需要拷贝的源Element对象
        /// \return IElement* 拷贝得到的Element对象指针
        virtual IElement* CopyElement(const IElement* pSourceElement) const = 0;

        /// \brief 批量拷贝Element对象
        ///
        /// \param pDocument 源文档指针
        /// \param sourceElementIds 需要拷贝的Elements的Id
        /// \param sourceToTargetIds 源Elements的Id和目标Elements的Id的映射表
        /// \param targetElementIds 拷贝得到的目标Elements的Id
        /// \return std::vector<ElementId> 返回被成功拷贝的源Elements的Id
        virtual std::vector<ElementId> CopyElements(
            IDocument* pDocument,
            const std::vector<ElementId>& sourceElementIds,
            const std::map<ElementId, ElementId>& sourceToTargetIds,
            std::set<ElementId>* targetElementIds
        ) const = 0;

        /// \brief 批量拷贝Element对象
        ///
        /// \param pDocument 源文档指针
        /// \param sourceElementIds 需要拷贝的Elements的Id
        /// \param sourceToTargetIds 源Elements的Id和目标Elements的Id的映射表，用于在Copy中做ElementId的替换
        /// \param allCopiedElementIds 所有拷贝得到的Elements的Id，可传nullptr
        /// \param targetModelviewId 拷贝后对象所在ModelView的Id,用于部分Element在拷贝后替换ModelViewId。替换逻辑需产品端在UpdateAfterCopy(const ICopyContext&)中自行实现
        /// \param extraCopiedSourceElementIds 额外需拷贝的源Elements对应的Id，可传nullptr
        /// \param allSourceToCopiedIdsMap 从源Element到拷贝得到Element的对应表，可传nullptr
        /// \return std::vector<ElementId> 返回从sourceElementIds成功拷贝得到的Elements的Id
        virtual std::vector<ElementId> CopyElements(
            IDocument* pDocument,
            const std::vector<ElementId>& sourceElementIds,
            const std::map<ElementId, ElementId>& sourceToTargetIds,
            std::set<ElementId>* allCopiedElementIds,
            const ElementId& targetModelviewId,
            std::set<ElementId>* extraCopiedSourceElementIds,
            std::map<ElementId, ElementId>* allSourceToCopiedIdsMap
        ) const = 0;

    public:
        // 临时性接口，因GBMP实现剪切板时需要去掉所有的非接口调用而暴露，不确定最终是否暴露
        /// \brief 通知被复制对象的WeakChildren其Parent被拷贝
        ///
        /// \param pDocumentFrom 复制操作源文档
        /// \param pDocumentTo 复制操作目标文档
        /// \param oldToNewElements 源文档对象到目标文档对象的映射关系集合
        /// \param allIdsToCopy 需要复制的对象
        /// \param oldToNewMap 源文档对象到目标文档对象Id的映射关系
        virtual void AskElementsToUpdateForWeakParentCopied(
            const IDocument* pDocumentFrom,
            IDocument* pDocumentTo,
            const std::vector<std::pair<const IElement*, IElement*> >& oldToNewElements,
            const std::set<ElementId>& allIdsToCopy,
            const std::map<ElementId, ElementId>& oldToNewMap
        ) const = 0;

    public:
        /// \brief 析构函数
        virtual ~ICopyOperator() = 0;

    public:
        /// \brief 构件级协同，判断拷贝后的构件是否具有编辑权限
        ///
        /// 默认是有编辑权限的
        ///
        /// \return bool true:有编辑权限；false：没有编辑权限
        virtual bool HasEditPrivilegeAfterCopy() const = 0;

        /// \brief 构件级协同，设置拷贝后的构件是否有编辑权限
        ///
        /// \param hasEditPrivilege 设置是否有编辑权限，true：有编辑权限，false：没有编辑权限
        /// \return bool 返回设置前的值，true：有编辑权限，false：没有编辑权限
        virtual bool SetHasEditPrivilegeAfterCopy(bool hasEditPrivilege) = 0;
    };
};





